---
title: Core Concepts
---

import { PubBadge } from '../src/components/Shield';
import mobxTriad from '../src/images/mobx-triad.png';
import mobxIsometric from '../src/images/mobx-isometric.png';

<img
  src={mobxTriad}
  alt="The Triad of MobX, consisting of Observable, Actions and Reactions"
/>

At the heart of MobX are three important concepts: **Observables**, **Actions**
and **Reactions**.

## Observables

Observables represent the reactive-state of your application. They can be simple
scalars to complex object trees. By defining the state of the application as a
tree of observables, you can expose a _reactive-state-tree_ that the UI (or
other observers in the app) consume.

> The term `reactive data` means that a change to data causes a notification to
> be fired to every interested observer. It is the application of the classic
> **Observer** Design Pattern.

A simple reactive-counter is represented by the following observable:

```dart
import 'package:mobx/mobx.dart';

final counter = Observable(0);
```

More complex observables, such as classes, can be created as well.

```dart
class Counter {
  Counter() {
    increment = Action(_increment);
  }

  final _value = Observable(0);
  int get value => _value.value;

  set value(int newValue) => _value.value = newValue;
  late Action increment;

  void _increment() {
    _value.value++;
  }
}
```

On first sight, this does look like some boilerplate code which can quickly go
out of hand! This is why we added <PubBadge name="mobx_codegen" /> to the mix
that allows you to replace the above code with the following:

```dart
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void increment() {
    value++;
  }
}
```

Note the use of annotations to mark the observable properties of the class. Yes,
there is some header boilerplate here but its fixed for any class. As you build
more complex classes, this boilerplate will fade away and you will mostly focus
on the code within the braces.

**Note**: Annotations are available via the <PubBadge name="mobx_codegen"/>
package.

The above code is part of the [**Counter Example**](/examples/counter).

> For those who have experience with the JavaScript version of MobX, it's
> important to note that deep observability doesn't apply in the Dart version of
> MobX. This is because Dart is a statically typed language and there's no
> support for reflection (no `dart:mirrors`) in Flutter applications. Therefore,
> if a complex object is marked as `@observable` then MobX will not be able to
> automatically track changes to the object's fields. Should you need change
> tracking at the field level, it's better to mark them individually with the
> `@observable` annotation.

## Computed Observables

> What can be derived, should be derived. Automatically.

The state of your application consists of _**core-state**_ and
_**derived-state**_. The _core-state_ is state inherent to the domain you are
dealing with. For example, if you have a `Contact` entity, the `firstName` and
`lastName` form the _core-state_ of `Contact`. However, `fullName` is
_derived-state_, obtained by combining `firstName` and `lastName`.

Such _derived state_, which depends on _core-state_ or _other derived-state_ is
called a **Computed Observable**. It is automatically kept in sync when its
underlying observables change.

> State in MobX = **Core-State** + **Derived-State**

```dart
import 'package:mobx/mobx.dart';

part 'contact.g.dart';

class Contact = ContactBase with _$Contact;

abstract class ContactBase with Store {
  @observable
  String firstName;

  @observable
  String lastName;

  @computed
  String get fullName => '$firstName, $lastName';

}
```

In the example above **`fullName`** is automatically kept in sync if either
`firstName` and/or `lastName` changes.

## Actions

Actions are how you mutate the observables. Rather than mutating them directly,
actions add a semantic meaning to the mutations. For example, instead of just
doing `value++`, firing an `increment()` action carries more meaning. Besides,
actions also batch up all the notifications and ensure the changes are notified
only after they complete. Thus, the observers are notified only upon the atomic
completion of the action.

Note that actions can also be nested, in which case the notifications go out
when the top-most action has completed.

```dart
final counter = Observable(0);

final increment = Action((){
  counter.value++;
});
```

When creating actions inside a class, you can take advantage of annotations!

```dart
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void increment() {
    value++;
  }
}
```

## Reactions

Reactions complete the _MobX triad_ of **observables**, **actions** and
**reactions**. They are the observers of the reactive-system and get notified
whenever an observable they track is changed. Reactions come in few flavors as
listed below. All of them return a `ReactionDisposer`, a function that can be
called to dispose the reaction.

One _striking feature_ of reactions is that they _automatically track_ all the
observables without any explicit wiring. The act of _reading an observable_
within a reaction is enough to track it!

> The code you write with MobX appears to be literally ceremony-free!

**`ReactionDisposer autorun(Function(Reaction) fn)`**

Runs the reaction immediately and also on any change in the observables used
inside `fn`.

```dart
import 'package:mobx/mobx.dart';

final greeting = Observable('Hello World');

final dispose = autorun((_){
  print(greeting.value);
});

greeting.value = 'Hello MobX';

// Done with the autorun()
dispose();


// Prints:
// Hello World
// Hello MobX
```

**`ReactionDisposer reaction<T>(T Function(Reaction) fn, void Function(T) effect)`**

Monitors the observables used inside the `fn()` function and runs the `effect()`
when the tracking function returns a different value. Only the observables
inside `fn()` are tracked.

```dart
import 'package:mobx/mobx.dart';

final greeting = Observable('Hello World');

final dispose = reaction((_) => greeting.value, (msg) => print(msg));

greeting.value = 'Hello MobX'; // Cause a change

// Done with the reaction()
dispose();


// Prints:
// Hello MobX
```

**`ReactionDisposer when(bool Function(Reaction) predicate, void Function() effect)`**

Monitors the observables used inside `predicate()` and runs the `effect()`
_when_ it returns `true`. After the `effect()` is run, `when` automatically
disposes itself. So you can think of _when_ as a _one-time_ `reaction`. You can
also dispose `when()` pre-maturely.

```dart
import 'package:mobx/mobx.dart';

final greeting = Observable('Hello World');

final dispose = when((_) => greeting.value == 'Hello MobX', () => print('Someone greeted MobX'));

greeting.value = 'Hello MobX'; // Causes a change, runs effect and disposes


// Prints:
// Someone greeted MobX
```

**`Future<void> asyncWhen(bool Function(Reaction) predicate)`**

Similar to `when` but returns a `Future`, which is fulfilled when the
`predicate()` returns _true_. This is a convenient way of waiting for the
`predicate()` to turn `true`.

```dart
final completed = Observable(false);

void waitForCompletion() async {
  await asyncWhen(() => completed.value == true);

  print('Completed');
}
```

## Observer

One of the most visual reactions in the app is the UI. The **Observer** widget
(which is part of the <PubBadge name="flutter_mobx" />), provides a granular
observer of the observables used in its `builder` function. Whenever these
observables change, `Observer` rebuilds and renders.

Below is the _Counter_ example in its entirety.

```dart
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void increment() {
    value++;
  }
}

class CounterExample extends StatefulWidget {
  const CounterExample();

  @override
  CounterExampleState createState() => CounterExampleState();
}

class CounterExampleState extends State<CounterExample> {
  final Counter counter = Counter();

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.blue,
          title: const Text('MobX Counter'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Observer(
                  builder: (_) => Text(
                        '${counter.value}',
                        style: const TextStyle(fontSize: 40),
                      )),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: counter.increment,
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      );
}
```

<img src={mobxIsometric} width="50%" />

## Deeper coverage

There are some articles written by
[Michel Weststrate](https://twitter.com/mweststrate) which go into the
philosophy of MobX. Definitely worth reading them.

- [The Fundamental Principles behind MobX](https://hackernoon.com/the-fundamental-principles-behind-mobx-7a725f71f3e8)
- [Becoming fully reactive - an in-depth explanation of MobX](https://hackernoon.com/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254)
